#include "Avalon/CodecsTests/CodedReaderTester.hpp"
#include "Avalon/IO/Buffer.hpp"
#include "Avalon/IO/BufferReader.hpp"
#include "Avalon/Codecs/CodedReader.hpp"
#include "Avalon/CodecsTests/ReverseDecoder.hpp"

using namespace Avalon;
using namespace Avalon::Codecs;
using namespace Avalon::Codecs::Tests;
using namespace Avalon::IO;
using namespace Avalon::Threading;
using namespace boost;
using namespace boost::posix_time;
using namespace std;

void CodedReaderTester::TestEmpty() {
  BufferReader bufferReader("");
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  CPPUNIT_ASSERT(codedReader.IsAtEndOfDataSource());
}

void CodedReaderTester::TestSingleByte() {
  BufferReader bufferReader("a");
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Buffer data;
  Async<int>::Ptr result = codedReader.Read(&data);
  CPPUNIT_ASSERT(result->Get(seconds(1)) == 1);
  CPPUNIT_ASSERT(data.GetSize() == 1);
  CPPUNIT_ASSERT(data.GetData()[0] == 'a');
  CPPUNIT_ASSERT(codedReader.IsAtEndOfDataSource());
}

void CodedReaderTester::TestRead() {
  string message = "hello world";
  string reverse = "dlrow olleh";
  BufferReader bufferReader(message);
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Buffer data;
  Async<int>::Ptr result = codedReader.Read(&data);
  CPPUNIT_ASSERT(result->Get(seconds(1)) == static_cast<int>(reverse.size()));
  CPPUNIT_ASSERT(data.GetSize() == static_cast<int>(reverse.size()));
  CPPUNIT_ASSERT(string(data.GetData(), data.GetSize()) == reverse);
  CPPUNIT_ASSERT(codedReader.IsAtEndOfDataSource());
}

void CodedReaderTester::TestReadSome() {
  string message = "helloworld";
  string firstReverse = "olleh";
  string secondReverse = "dlrow";
  BufferReader bufferReader(message);
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Buffer data;
  Async<int>::Ptr result = codedReader.Read(&data,
    static_cast<int>(firstReverse.size()));
  CPPUNIT_ASSERT(result->Get(seconds(1)) ==
    static_cast<int>(firstReverse.size()));
  CPPUNIT_ASSERT(data.GetSize() == static_cast<int>(firstReverse.size()));
  CPPUNIT_ASSERT(string(data.GetData(), data.GetSize()) == firstReverse);
  data.Reset();
  result = codedReader.Read(&data, static_cast<int>(secondReverse.size()));
  CPPUNIT_ASSERT(result->Get(seconds(1)) == static_cast<int>(
    secondReverse.size()));
  CPPUNIT_ASSERT(data.GetSize() == static_cast<int>(secondReverse.size()));
  CPPUNIT_ASSERT(string(data.GetData(), data.GetSize()) == secondReverse);
  CPPUNIT_ASSERT(codedReader.IsAtEndOfDataSource());
}
